home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / zip.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  13KB  |  416 lines

  1. // $Id: zip.cpp,v 1.6 1999/08/26 15:34:11 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <assert.h>
  12. #include <iostream.h>
  13. #include <string.h>
  14. #include "control.h"
  15. #include "zip.h"
  16. #include "symbol.h"
  17.  
  18. //************************************************************************************************
  19. //
  20. // The ZipFile methods follow
  21. //
  22. //************************************************************************************************
  23. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  24.     int (*ZipFile::uncompress_file[10]) (FILE *, char *, long) =
  25.     {
  26.         UncompressFile0,
  27.         UncompressFile1,
  28.         UncompressFile2,
  29.         UncompressFile3,
  30.         UncompressFile4,
  31.         UncompressFile5,
  32.         UncompressFile6,
  33.         UncompressFile7,
  34.         UncompressFile8,
  35.         UncompressFile9
  36.     };
  37.  
  38.     inline u1 ZipFile::GetU1()
  39.     {
  40.         return getc(zipfile);
  41.     }
  42.  
  43.     inline void ZipFile::Skip(u4 length)
  44.     {
  45.         for (u4 i = 0; i < length; i++)
  46.              getc(zipfile);
  47.     }
  48.  
  49. #elif defined(WIN32_FILE_SYSTEM)
  50.  
  51.     int (*ZipFile::uncompress_file[10]) (char *, char *, long) =
  52.     {
  53.         UncompressFile0,
  54.         UncompressFile1,
  55.         UncompressFile2,
  56.         UncompressFile3,
  57.         UncompressFile4,
  58.         UncompressFile5,
  59.         UncompressFile6,
  60.         UncompressFile7,
  61.         UncompressFile8,
  62.         UncompressFile9
  63.     };
  64.  
  65.     inline u1 ZipFile::GetU1()
  66.     {
  67.         return *file_buffer++;
  68.     }
  69.  
  70.     inline void ZipFile::Skip(u4 length)
  71.     {
  72.         file_buffer += length;
  73.     }
  74.  
  75. #endif
  76.  
  77.  
  78. inline u2 ZipFile::GetU2()
  79. {
  80.     u4 val = GetU1();
  81.     val |= (((u4) GetU1()) << 8);
  82.  
  83.     return val;
  84. }
  85.  
  86.  
  87. inline u4 ZipFile::GetU4()
  88. {
  89.     u4 val = GetU1();
  90.     val |= (((u4) GetU1()) << 8);
  91.     val |= (((u4) GetU1()) << 16);
  92.     val |= (((u4) GetU1()) << 24);
  93.  
  94.     return val;
  95. }
  96.  
  97.  
  98. ZipFile::ZipFile(FileSymbol *file_symbol) : buffer(NULL)
  99. {
  100.     Zip *zip = file_symbol -> Zipfile();
  101.  
  102.     assert(zip -> IsValid());
  103.  
  104. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  105.     zipfile = zip -> zipfile;
  106.     int rc = fseek(zipfile, file_symbol -> offset, SEEK_SET);
  107.  
  108.     assert(rc == 0);
  109.  
  110. #elif defined(WIN32_FILE_SYSTEM)
  111.     file_buffer = &zip -> zipbuffer[file_symbol -> offset];
  112. #endif
  113.  
  114.     Skip(8); // u4 magic                     = GetU4();
  115.              // u2 version_needed_to_extract = GetU2();
  116.              // u2 general_purpose_bits      = GetU2();
  117.     u2 compression_method                    = GetU2();
  118.     Skip(16); // u2 time                     = GetU2();
  119.               // u2 date                     = GetU2();
  120.               // u4 crc32                    = GetU4();
  121.               // u4 compressed_size          = GetU4();
  122.               // u4 uncompressed_size        = GetU4();
  123.     u2 filename_length                       = GetU2();
  124.     u2 extra_field_length                    = GetU2();
  125.     Skip(filename_length + extra_field_length);
  126.  
  127. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  128.     this -> buffer = new char[file_symbol -> uncompressed_size];
  129.     if (! uncompress_file[compression_method < 9 ? compression_method : 9](zipfile, this -> buffer, file_symbol -> uncompressed_size))
  130.     {
  131.         delete [] this -> buffer;
  132.         this -> buffer = NULL;
  133.     }
  134. #elif defined(WIN32_FILE_SYSTEM)
  135.     if (compression_method > 0)
  136.     {
  137.         this -> buffer = new char[file_symbol -> uncompressed_size];
  138.         if (! uncompress_file[compression_method < 9 ? compression_method : 9](file_buffer,
  139.                                                                                this -> buffer,
  140.                                                                                file_symbol -> uncompressed_size))
  141.         {
  142.             delete [] this -> buffer;
  143.             this -> buffer = NULL;
  144.             this -> file_buffer = NULL;
  145.         }
  146.     }
  147. #endif
  148.  
  149.     return;
  150. }
  151.  
  152.  
  153. ZipFile::~ZipFile()
  154. {
  155.     delete [] buffer;
  156. }
  157.  
  158.  
  159. //************************************************************************************************
  160. //
  161. // The Zip methods follow:
  162. //
  163. //************************************************************************************************
  164. inline u1 Zip::GetU1()
  165. {
  166.     return *buffer_ptr++;
  167. }
  168.  
  169.  
  170. inline u2 Zip::GetU2()
  171. {
  172.     u4 val = GetU1();
  173.     val |= (((u4) GetU1()) << 8);
  174.  
  175.     return val;
  176. }
  177.  
  178.  
  179. inline u4 Zip::GetU4()
  180. {
  181.     u4 val = GetU1();
  182.     val |= (((u4) GetU1()) << 8);
  183.     val |= (((u4) GetU1()) << 16);
  184.     val |= (((u4) GetU1()) << 24);
  185.  
  186.     return val;
  187. }
  188.  
  189.  
  190. inline void Zip::Skip(u4 length)
  191. {
  192.     buffer_ptr += length;
  193. }
  194.  
  195.  
  196. inline DirectorySymbol *Zip::ProcessSubdirectoryEntries(DirectorySymbol *directory_symbol, char *name, int name_length)
  197. {
  198.     wchar_t *directory_name = new wchar_t[name_length];
  199.  
  200.     for (int start = 0, end; start < name_length; start = end + 1)
  201.     {
  202.         end = start;
  203.         for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  204.              directory_name[i] = name[end];
  205.         NameSymbol *name_symbol = control.FindOrInsertName(directory_name, end - start);
  206.         DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  207.         if (! subdirectory_symbol)
  208.             subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  209.         directory_symbol = subdirectory_symbol;
  210.     }
  211.  
  212.     delete [] directory_name;
  213.  
  214.     return directory_symbol;
  215. }
  216.  
  217.  
  218. inline NameSymbol *Zip::ProcessFilename(char *name, int name_length)
  219. {
  220.     wchar_t *input_filename = new wchar_t[name_length];
  221.     for (int i = 0; i < name_length; i++)
  222.         input_filename[i] = name[i];
  223.     NameSymbol *name_symbol = control.FindOrInsertName(input_filename, name_length);
  224.  
  225.     delete [] input_filename;
  226.  
  227.     return name_symbol;
  228. }
  229.  
  230.  
  231. inline void Zip::ProcessDirectoryEntry()
  232. {
  233.     Skip(8); // u2 version_made_by           = GetU2();
  234.              // u2 version_needed_to_extract = GetU2();
  235.              // u2 general_purpose_bits      = GetU2();
  236.              // u2 compression_method        = GetU2();
  237.     u2 last_mod_file_time                    = GetU2();
  238.     u2 last_mod_file_date                    = GetU2();
  239.     Skip(4); // u4 crc32                     = GetU4();
  240.     Skip(4); // u4 compressed_size           = GetU4();
  241.     u4 uncompressed_size                     = GetU4();
  242.     u2 file_name_length                      = GetU2();
  243.     u2 extra_field_length                    = GetU2();
  244.     u2 file_comment_length                   = GetU2();
  245.     Skip(8); // u2 disk_number_start         = GetU2();
  246.              // u2 internal_file_attributes  = GetU2();
  247.              // u4 external_file_attributes  = GetU4();
  248.     u4 relative_offset_of_local_header       = GetU4();
  249.  
  250.     u4 date_time = ((u4) last_mod_file_date) << 16 | last_mod_file_time;
  251.     char *name = buffer_ptr;
  252.  
  253.     Skip(file_name_length + extra_field_length + file_comment_length);
  254.  
  255.     //
  256.     // Note that we need to process all subdirectory entries that appear in the zip file, and not
  257.     // just the ones that contain java and class files. Recall that in java the dot notation is
  258.     // used in specifying a package. Therefore, in processing a qualified-name that represents
  259.     // a package, we need to recognize each name as a subpackage. E.g., when processing
  260.     // "java.lang", we need to recognize "java" as a package before looking for "lang"...
  261.     //
  262.     DirectorySymbol *directory_symbol = root_directory; // start at the "." directory.
  263.     if (name[file_name_length - 1] == U_SLASH)
  264.         ProcessSubdirectoryEntries(directory_symbol, name, file_name_length - 1);  // -1 to remove last '/'
  265.     else
  266.     {
  267.         bool java_file = (file_name_length >= FileSymbol::java_suffix_length &&
  268.                           FileSymbol::IsJavaSuffix(&name[file_name_length - FileSymbol::java_suffix_length])),
  269.              class_file = (file_name_length >= FileSymbol::class_suffix_length &&
  270.                            FileSymbol::IsClassSuffix(&name[file_name_length - FileSymbol::class_suffix_length]));
  271.  
  272.         if (java_file || class_file)
  273.         {
  274.             int name_length = file_name_length - (java_file ? FileSymbol::java_suffix_length : FileSymbol::class_suffix_length);
  275.             int i;
  276.             for (i = name_length - 1; i >= 0 && name[i] != U_SLASH; i--)
  277.                 ;
  278.             if (i > 0) // directory specified?
  279.                 directory_symbol = ProcessSubdirectoryEntries(directory_symbol, name, i);
  280.             NameSymbol *name_symbol = ProcessFilename(&name[i + 1], name_length - (i + 1));
  281.  
  282.             //
  283.             // Search for a file of that name in the directory. If one is not found, then insert ...
  284.             // Otherwise, either a class file of that name was previously processed and now we found
  285.             // a java file with the same name or vice-versa... In that case keep (or replace with ) the
  286.             // the file with the most recent date stamp.
  287.             //
  288.             FileSymbol *file_symbol = directory_symbol -> FindFileSymbol(name_symbol);
  289.             if (! file_symbol)
  290.             {
  291.                 file_symbol = directory_symbol -> InsertFileSymbol(name_symbol);
  292.  
  293.                 file_symbol -> directory_symbol = directory_symbol;
  294.                 if (java_file)
  295.                      file_symbol -> SetJava();
  296.                 else file_symbol -> SetClassOnly();
  297.  
  298.                 file_symbol -> uncompressed_size = uncompressed_size;
  299.                 file_symbol -> offset = relative_offset_of_local_header;
  300.                 file_symbol -> date_time = date_time;
  301.             }
  302.             else if (file_symbol -> date_time < date_time)
  303.             {
  304.                 if (java_file)
  305.                      file_symbol -> SetJava();
  306.                 else file_symbol -> SetClass();
  307.  
  308.                 file_symbol -> uncompressed_size = uncompressed_size;
  309.                 file_symbol -> offset = relative_offset_of_local_header;
  310.                 file_symbol -> date_time = date_time;
  311.             }
  312.         }
  313.     }
  314.  
  315.     return;
  316. }
  317.  
  318.  
  319. Zip::Zip(Control &control_, char *zipfile_name) : control(control_),
  320.                                                   magic(0),
  321.                                                   zipbuffer(NULL)
  322. {
  323. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  324.     zipfile = ::SystemFopen(zipfile_name, "rb");
  325.     if (zipfile)
  326.     {
  327.         int rc = fseek(zipfile, -22, SEEK_END);
  328.         if (rc == 0);
  329.         {
  330.             zipbuffer = new char[22];
  331.             buffer_ptr = zipbuffer;
  332.             fread(buffer_ptr, sizeof(char), 22, zipfile);
  333.  
  334.             magic = GetU4();
  335.         }
  336.     }
  337. #elif defined(WIN32_FILE_SYSTEM)
  338.     zipfile = CreateFile(zipfile_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
  339.     if (zipfile != INVALID_HANDLE_VALUE)
  340.     {
  341.         mapfile = CreateFileMapping(zipfile, NULL, PAGE_READONLY, 0, 0, NULL);
  342.         zipbuffer = (mapfile == INVALID_HANDLE_VALUE ? NULL : (char *) MapViewOfFile(mapfile, FILE_MAP_READ, 0, 0, 0));
  343.         if (zipbuffer)
  344.         {
  345.             buffer_ptr = &zipbuffer[GetFileSize(zipfile, NULL) - 22];
  346.             magic = GetU4();
  347.         }
  348.     }
  349. #endif
  350.  
  351.     ReadDirectory();
  352.  
  353.     return;
  354. }
  355.  
  356.  
  357. Zip::~Zip()
  358. {
  359. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  360.     delete [] zipbuffer;
  361.     if (zipfile)
  362.         fclose(zipfile);
  363. #elif defined(WIN32_FILE_SYSTEM)
  364.     if (zipfile != INVALID_HANDLE_VALUE)
  365.     {
  366.         if (mapfile != INVALID_HANDLE_VALUE)
  367.         {
  368.             if (zipbuffer)
  369.                 UnmapViewOfFile(zipbuffer);
  370.             CloseHandle(mapfile);
  371.         }
  372.         CloseHandle(zipfile);
  373.     }
  374. #endif
  375.  
  376.     delete root_directory;
  377. }
  378.  
  379.  
  380. //
  381. // Upon successful termination of this function, IsValid() should yield true.
  382. // I.e., we should be able to assert that (magic == 0x06054b50)
  383. //
  384. void Zip::ReadDirectory()
  385. {
  386.     root_directory = new DirectorySymbol(control.dot_name_symbol, NULL);
  387.  
  388.     if (IsValid())
  389.     {
  390.         Skip(8); // u2 number_of_this_disk              = GetU2();
  391.                  // u2 number_of_the_disk_with_the_star = GetU2();
  392.                  // u2 start_of_the_central_directory   = GetU2();
  393.                  // u2 total_number_of_entries_in_the_  = GetU2();
  394.         u4 central_directory_size                       = GetU4();
  395.  
  396. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  397.         int rc = fseek(zipfile, -((int) central_directory_size + 22), SEEK_END);
  398.  
  399.         assert(rc == 0);
  400.  
  401.         delete [] zipbuffer;
  402.         zipbuffer = new char[central_directory_size + 22];
  403.         buffer_ptr = zipbuffer;
  404.         fread(buffer_ptr, sizeof(char), central_directory_size + 22, zipfile);
  405. #elif defined(WIN32_FILE_SYSTEM)
  406.         buffer_ptr -= (central_directory_size + 16);
  407. #endif
  408.         for (magic = GetU4(); magic == 0x02014b50; magic = GetU4())
  409.              ProcessDirectoryEntry();
  410.     }
  411.  
  412.     return;
  413. }
  414.  
  415.  
  416.